package com.hk.core.jdbc;

import com.hk.commons.query.OrderUtils;
import com.hk.commons.util.AssertUtils;
import com.hk.commons.util.CollectionUtils;
import com.hk.commons.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author Kevin
 * @date 2022/11/21 22:56
 */
public record SelectStatement(StringBuilder selectSql, StringBuilder countSql, List<Object> parameters) {

    public static SelectStatement buildSelect(SelectArguments arguments) {
        AssertUtils.isTrue(Objects.nonNull(arguments), "arguments must not be null");
        AssertUtils.notEmpty(arguments.getFrom(), "查询表名不能为空");
        var sql = new StringBuilder();
        var countSql = new StringBuilder();

        var fieldSet = arguments.getFields();
        var fields = CollectionUtils.isEmpty(fieldSet) ? "*"
                : String.join(StringUtils.COMMA_SEPARATE, fieldSet);
        sql.append("SELECT ");
        countSql.append("SELECT ");
        if (arguments.isDistinct()) {
            sql.append("DISTINCT ");
            countSql.append("DISTINCT ");
        }
        sql.append(fields);
        sql.append(" FROM ");
        var countField = arguments.getCountField();
        countSql.append("COUNT(").append(StringUtils.defaultIfEmpty(countField, "*")).append(") FROM ");

        sql.append(arguments.getFrom());
        countSql.append(arguments.getFrom());

        var parameters = new ArrayList<>();
        var condition = arguments.getConditions();
        if (null != condition) {
            var parametric = arguments.getParametric();
            var conditionSql = Objects.isNull(parametric) ? condition.toSqlString(parameters)
                    : condition.toSqlString(parametric, parameters);
            if (StringUtils.isNotEmpty(conditionSql)) {
                sql.append(" WHERE ");
                sql.append(conditionSql);
                countSql.append(" WHERE ");
                countSql.append(conditionSql);
            }
        }
        var groupBys = arguments.getGroupBy();
        if (CollectionUtils.isNotEmpty(groupBys)) {
            var groupBySql = String.join(StringUtils.COMMA_SEPARATE, groupBys);
            sql.append(" GROUP BY ").append(groupBySql);
            countSql.append(" GROUP BY ").append(groupBySql).append(") result_");
            countSql.insert(0, "SELECT COUNT(*) FROM (");
        }
        sql.append(OrderUtils.toOrderSql(arguments.getOrders()));
        return new SelectStatement(sql, countSql, parameters);
    }
}
